package com.force.common.h2.service;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.rolling.RollingFileAppender;
import com.force.common.h2.models.H2JdbcTemplate;
import com.force.common.h2.models.ZincLogVo;
import org.springframework.boot.jdbc.DataSourceBuilder;

import javax.sql.DataSource;
import java.util.Optional;

public class H2Appender extends RollingFileAppender<ILoggingEvent> {


    H2JdbcTemplate h2JdbcTemplate;
    public DataSource dataSource() {
        return DataSourceBuilder.create()
                .driverClassName("org.h2.Driver")
                .url("jdbc:h2:file:./h2/testdb.db")
                .username("sa")
                .password("123123")
                .build();
    }
    public H2Appender() {
        super();
    }
    @Override
    protected void append(ILoggingEvent event) {
        super.append(event);
        if(h2JdbcTemplate ==null){
            h2JdbcTemplate = new H2JdbcTemplate(dataSource());
            if (!doesTableExist(h2JdbcTemplate,"LOGS")) {
                init(h2JdbcTemplate);
            }
        }
        if (h2JdbcTemplate != null) {
            ZincLogVo zincLogVo = parseEvent(event);
            saveLog(zincLogVo);
        }
    }




    public ZincLogVo parseEvent(Object event) {

        ZincLogVo vo = new ZincLogVo();
        vo.setGroupName("tracelog");
        String replaceContent = ((LoggingEvent) event).getFormattedMessage().replace("'", "");
        vo.setContent(replaceContent);
        vo.setLevel(((LoggingEvent) event).getLevel().toString());
        if(null!=((LoggingEvent) event).getThrowableProxy()){
            vo.setThrowableMsg(Optional.of(((LoggingEvent) event).getThrowableProxy().getMessage()).orElse(null));
        }
        vo.setLoggerName(((LoggingEvent) event).getLoggerName());
        vo.setThreadName(((LoggingEvent) event).getThreadName());
        vo.setTraceId(Optional.of(((LoggingEvent) event).getMDCPropertyMap().get("TRACE_ID")).orElse(null));
        vo.setClientIp(Optional.of(((LoggingEvent) event).getMDCPropertyMap().get("CLIENT_IP")).orElse(null));
        vo.setTimestamp("CURRENT_TIMESTAMP");
        return vo;
    }

    public void saveLog(ZincLogVo log) {
        String sql = "INSERT INTO LOGS (group_name," +
                "thread_name, " +
                "logger_name, content, level, throwable_msg, trace_id, client_ip, timestamp) " +
                "VALUES ('" + log.getGroupName() + "', '" + log.getThreadName() + "', '" + log.getLoggerName() + "', '" + log.getContent() + "', '" + log.getLevel() + "', '" +
                log.getThrowableMsg() + "', '" + log.getTraceId() + "', '" + log.getClientIp() + "', " + log.getTimestamp() + ")";
        h2JdbcTemplate.execute(sql);
    }
    public void init(H2JdbcTemplate h2JdbcTemplate) {
        h2JdbcTemplate.execute("CREATE TABLE LOGS (" +
                "id BIGINT AUTO_INCREMENT PRIMARY KEY," +
                "group_name VARCHAR(255)," +
                "thread_name VARCHAR(255)," +
                "logger_name VARCHAR(255)," +
                "content CLOB," +
                "level VARCHAR(50)," +
                "throwable_msg CLOB," +
                "trace_id VARCHAR(255)," +
                "client_ip VARCHAR(255)," +
                "timestamp TIMESTAMP" +
                ")");
    }
    public boolean doesTableExist(H2JdbcTemplate h2JdbcTemplate,String tableName) {
        String sql = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = ?";
        Integer count = h2JdbcTemplate.queryForObject(sql, new Object[] { tableName.toUpperCase() }, Integer.class);
        return count != null && count > 0;
    }
}
